//    Copyright (C) Kherty.  All rights reserved.
using System;

namespace OpenLS.Spreadsheet.StandardAddIn.Statistics
{
    internal abstract class ContinuousDistribution : Distribution
    {
        public virtual double InverseCumulativeProbability(double probability)
        {
            CheckValidProperty(probability);
            DoubleFunction rootFindingFunction =
                x => CumulativeProbability(x) - probability;


            // Try to bracket root, test domain endoints if this fails	 
            double lowerBound =  GetSolverParameters(probability).LowerValue;
            double upperBound = GetSolverParameters(probability).UpperValue;
            double initial = GetSolverParameters(probability).InitialValue;
            double[] bracket;
            try
            {
                bracket = SolverUtils.bracket(
                    rootFindingFunction, initial,
                    lowerBound, upperBound);
            }
            catch (ConvergenceException)
            {
                if (Math.Abs(rootFindingFunction(lowerBound)) < 1E-6)
                {
                    return lowerBound;
                }
                if (Math.Abs(rootFindingFunction(upperBound)) < 1E-6)
                {
                    return upperBound;
                }
                if (Math.Abs(rootFindingFunction(initial)) < 1E-6)
                {
                    return initial;
                }
                throw new MathException();
            }
            double result = SolverUtils.Solve(rootFindingFunction, bracket[0], bracket[1], 1e-9);
            return result;
        }


        protected abstract SolverParameters GetSolverParameters(double probability);
    }
}